package com.ebo.learn_demo.view

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.core.view.NestedScrollingParent3
import androidx.core.view.NestedScrollingParentHelper

/**
 * @author zmp
 * @date : 2021/8/20 16:21
 * des:NestedScrollingParent3
 */
class MySwipeLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayoutCompat(context, attrs, defStyleAttr), NestedScrollingParent3 {
    private val mNestedScrollingParentHelper by lazy {
        NestedScrollingParentHelper(this)
    }

    /**
     * 有嵌套滑动到来了，判断父view是否接受嵌套滑动
     *
     * @param child            嵌套滑动对应的父类的子类(因为嵌套滑动对于的父View不一定是一级就能找到的，可能挑了两级父View的父View，child的辈分>=target)
     * @param target           具体嵌套滑动的那个子类
     * @param axes 支持嵌套滚动轴。水平方向，垂直方向，或者不指定
     * @param type             滑动类型，ViewCompat.TYPE_NON_TOUCH fling 效果ViewCompat.TYPE_TOUCH 手势滑动
     */
    override fun onStartNestedScroll(child: View, target: View, axes: Int, type: Int): Boolean {
        return true
    }

    override fun onStartNestedScroll(child: View, target: View, axes: Int): Boolean {
        return true
    }

    override fun onNestedScrollAccepted(child: View, target: View, axes: Int, type: Int) {
        mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, axes, type)
    }

    override fun onNestedScrollAccepted(child: View, target: View, axes: Int) {
        mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, axes)
    }

    override fun onStopNestedScroll(target: View, type: Int) {
        mNestedScrollingParentHelper.onStopNestedScroll(target, type)
        Log.e(TAG, "onStopNestedScroll(target: View, type: Int) type :$type")
    }

    override fun onStopNestedScroll(target: View) {
        mNestedScrollingParentHelper.onStopNestedScroll(target)
        Log.e(TAG, "onStopNestedScroll(target: View)")
    }

    /**
     * 嵌套滑动的子View在滑动之后，判断父view是否继续处理（也就是父消耗一定距离后，子再消耗，最后判断父消耗不）
     *
     * @param target       具体嵌套滑动的那个子类
     * @param dxConsumed   水平方向嵌套滑动的子View滑动的距离(消耗的距离)
     * @param dyConsumed   垂直方向嵌套滑动的子View滑动的距离(消耗的距离)
     * @param dxUnconsumed 水平方向嵌套滑动的子View未滑动的距离(未消耗的距离)
     * @param dyUnconsumed 垂直方向嵌套滑动的子View未滑动的距离(未消耗的距离)
     * @param type         滑动类型，[androidx.core.view.ViewCompat.TYPE_NON_TOUCH] fling 效果ViewCompat.TYPE_TOUCH 手势滑动
     */
    override fun onNestedScroll(
        target: View,
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int,
        type: Int,
        consumed: IntArray
    ) {
        Log.e(
            TAG,
            """
               onNestedScroll: target:$target ,dxConsumed:$dxConsumed 
               ,dyConsumed :$dyConsumed ,dxUnconsumed:$dxUnconsumed 
               ,dyUnconsumed:$dyUnconsumed ,type:$type
               ,consumed:${consumed.joinToString()}" 
            """.trimIndent()
        )
        if (dyUnconsumed < 0) {
            scrollBy(0, dyUnconsumed)
            if (scrollY <= 0 && dyUnconsumed < 0) {
                consumed[1] = 0
            } else if (scrollY >= mTopViewHeight && dyUnconsumed > 0) {
                consumed[1] = 0
            } else {
                consumed[1] = dyUnconsumed
            }
        }
    }


    override fun onNestedScroll(
        target: View,
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int,
        type: Int
    ) {}

//    override fun onNestedScroll(
//        target: View,
//        dxConsumed: Int,
//        dyConsumed: Int,
//        dxUnconsumed: Int,
//        dyUnconsumed: Int
//    ) {
//
//    }

    /**
     * 在嵌套滑动的子View未滑动之前，判断父view是否优先与子view处理(也就是父view可以先消耗，然后给子view消耗）
     *
     * @param target   具体嵌套滑动的那个子类
     * @param dx       水平方向嵌套滑动的子View想要变化的距离
     * @param dy       垂直方向嵌套滑动的子View想要变化的距离 dy<0向下滑动 dy>0 向上滑动
     * @param consumed 这个参数要我们在实现这个函数的时候指定，回头告诉子View当前父View消耗的距离
     *                 consumed[0] 水平消耗的距离，consumed[1] 垂直消耗的距离 好让子view做出相应的调整
     * @param type     滑动类型，ViewCompat.TYPE_NON_TOUCH fling 效果ViewCompat.TYPE_TOUCH 手势滑动
     */
    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
        Log.e(
            TAG,
            "onNestedPreScroll: target:$target dx:$dx ,dy ：$dy ,consumed:${consumed.joinToString()} ,type:$type"
        )
        //这里不管手势滚动还是fling都处理
        val hideTop = dy > 0 && scrollY < mTopViewHeight
        if (hideTop) {
            val coerceAtMost = dy.coerceAtMost(mTopViewHeight - scrollY)
            scrollBy(0, coerceAtMost)
            consumed[1] = coerceAtMost
            return
        }
        val showTop = dy < 0 && scrollY >= 0 && target.scrollY == 0
        if (showTop) {
            val coerceAtMost = dy.coerceAtLeast(0 - scrollY)
            scrollBy(0, coerceAtMost)
            consumed[1] = coerceAtMost
            return
        }
    }

//    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) {
//
//    }

    override fun onNestedFling(
        target: View,
        velocityX: Float,
        velocityY: Float,
        consumed: Boolean
    ): Boolean {
        return false
    }

    override fun onNestedPreFling(target: View, velocityX: Float, velocityY: Float): Boolean {
        return false
    }

    override fun getNestedScrollAxes(): Int {
        return mNestedScrollingParentHelper.nestedScrollAxes
    }

    private val mTopViewHeight by lazy {
        getChildAt(0).measuredHeight
    }

    /**
     * 符号与实际方向相反
     */
    override fun scrollTo(x: Int, y: Int) {
        var resultY = y
        if (resultY < 0) {
            resultY = 0
        }
        if (resultY > mTopViewHeight) {
            resultY = mTopViewHeight
        }
        Log.e(TAG, "scrollTo: $resultY")
        super.scrollTo(x, resultY)
    }

    companion object {
        private const val TAG = "MySwipeLayout"
    }
}